/*
 * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.dona.imsidetector.socket;

import android.content.Context;
import android.os.Message;
import android.util.Log;

import com.dona.imsidetector.bean.ImsiBean;
import com.dona.imsidetector.db.XUtilsManager;
import com.dona.imsidetector.db.entity.Imsi;
import com.dona.imsidetector.fragment.DetectorFragment;
import com.dona.imsidetector.utils.DeviceUtil;
import com.dona.imsidetector.utils.IMSIUtil;
import com.umeng.commonsdk.debug.I;

import org.xutils.ex.DbException;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import io.reactivex.internal.util.LinkedArrayList;

//import melo.com.udpsocketdemo.bean.Users;


/**
 * Created by melo on 2017/9/20.
 */

public class UDPSocket {

    private static final String TAG = "UDPSocket";

    // 单个CPU线程池大小
    private static final int POOL_SIZE = 5;

    private static final int BUFFER_LENGTH = 1024;
    public static String scanText = "离线，等待设备上线";
    private byte[] receiveByte = new byte[BUFFER_LENGTH];

    private static final String BROADCAST_IP = "192.168.1.90";

    // 端口号，飞鸽协议默认端口2425
    public static final int CLIENT_PORT = 9001;

    private boolean isThreadRunning = false;

    private Context mContext;
    private DatagramSocket client;
    private DatagramPacket receivePacket;

    private long lastReceiveTime = 0;
    private static final long TIME_OUT = 20 * 1000;
    private static final long HEARTBEAT_MESSAGE_DURATION = 10 * 1000;

    private ExecutorService mThreadPool;
    private Thread clientThread;
    private HeartbeatTimer timer;

    public static LinkedBlockingQueue imsibd = null;
    public static LinkedList<Imsi> imsilist = null;
    public static LinkedList<String> imsistrlist = null;
    public static int imsi_status = 0;

//    private Users localUser;
//    private Users remoteUser;


    public UDPSocket(Context context) {

        this.mContext = context;

        int cpuNumbers = Runtime.getRuntime().availableProcessors();
        // 根据CPU数目初始化线程池
        mThreadPool = Executors.newFixedThreadPool(cpuNumbers * POOL_SIZE);
        // 记录创建对象时的时间
        lastReceiveTime = System.currentTimeMillis();

//        createUser();
    }

    /**
     * 获取个数
     * @return
     */
    public int getSize(){
        return imsistrlist==null?0:imsistrlist.size();
    }


    /**
     * 创建本地用户信息
     */
//    private void createUser() {
//        if (localUser == null) {
//            localUser = new Users();
//        }
//        if (remoteUser == null) {
//            remoteUser = new Users();
//        }
//
//        localUser.setImei(DeviceUtil.getDeviceId(mContext));
//        localUser.setSoftVersion(DeviceUtil.getPackageVersionCode(mContext));
//
//        if (WifiUtil.getInstance(mContext).isWifiApEnabled()) {// 判断当前是否是开启热点方
//            localUser.setIp("192.168.43.1");
//        } else {// 当前是开启 wifi 方
//            localUser.setIp(WifiUtil.getInstance(mContext).getLocalIPAddress());
//            remoteUser.setIp(WifiUtil.getInstance(mContext).getServerIPAddress());
//        }
//    }


    public void startUDPSocket() {
        if (client != null) return;
        try {
            // 表明这个 Socket 在设置的端口上监听数据。

            client = new DatagramSocket(null);
            client.setReuseAddress(true);
            client.bind(new InetSocketAddress(CLIENT_PORT));
            if (receivePacket == null) {
                // 创建接受数据的 packet
                receivePacket = new DatagramPacket(receiveByte, BUFFER_LENGTH);
            }

//            imsibd = new LinkedBlockingQueue();
            imsilist = new LinkedList();
            imsistrlist = new LinkedList();

            startSocketThread();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    /**
     * 开启发送数据的线程
     */
    private void startSocketThread() {
        clientThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "clientThread is running...");
                receiveMessage();
            }
        });
        isThreadRunning = true;
        clientThread.start();

        startHeartbeatTimer();
    }

    private static String currFreq = "";
    public static boolean isOnScaning = false;


    /**
     * 处理接受到的消息
     */
    private void receiveMessage() {
        while (isThreadRunning) {
            try {
                if (client != null) {
                    client.receive(receivePacket);
                }
                lastReceiveTime = System.currentTimeMillis();
                Log.d(TAG, "receive packet success...");
            } catch (IOException e) {
                Log.e(TAG, "UDP数据包接收失败！线程停止");
                stopUDPSocket();
                e.printStackTrace();
                return;
            }

            if (receivePacket == null || receivePacket.getLength() == 0) {
                Log.e(TAG, "无法接收UDP数据或者接收到的UDP数据为空");
                continue;
            }

            String strReceive = new String(receivePacket.getData(), 0, receivePacket.getLength());
            Log.e(TAG, strReceive + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());

            if(strReceive.contains("STATE")){

            }
            if(strReceive.indexOf("103")==0){
                String imsi_str = IMSIUtil.getData( strReceive,"imsi") ;
                String time_str = IMSIUtil.getData( strReceive,"time") ;
                String power_str = IMSIUtil.getData( strReceive,"ulSig") ;

                Imsi imsi = new Imsi();
                imsi.setImsi(imsi_str);
                imsi.setTime(Long.valueOf(time_str));
                imsi.setPower(Float.valueOf(power_str));



                try {
//                    imsibd.put(imsi);
                    boolean fff = true;
                    for (int i = 0; i < imsilist.size(); i++) {
                        Imsi imsi1 = imsilist.get(i);
                        if (imsi1.getImsi().equals(imsi_str)) {
                            imsilist.remove(i);
                            imsistrlist.remove(i);
                            imsilist.add(0, imsi);
                            imsistrlist.add(0, imsi_str + "["+power_str+"][" + currFreq +"]  " + DeviceUtil.stampToDate(time_str));
                            fff = false;
                        }
                    }
                    if (fff) {
                        imsilist.add(imsi);
                        imsistrlist.add( imsi_str + "["+power_str+"][" + currFreq +"]  " + DeviceUtil.stampToDate(time_str));

                    }



//                    XUtilsManager.getInstance().getDbManager().save(imsi);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                imsi_status = 1;
            }


            if(strReceive.indexOf("101") == 0){
                currFreq = IMSIUtil.getData(strReceive,"FREQ");
                scanText = "在线";
            }else if(strReceive.indexOf("116") == 0){
//                isOnScaning = true;
                scanText = "扫描中";
            }

            //解析接收到的 json 信息
//            103 OneUeInfoIndi PS_WL S2A4A2109059 time[4562] taType[TA_REQ] imsi[460023148087839] imei[000000000000000] ulSig[93] ulTa[14] bl_indi[0]  from 192.168.1.90:9001
            // 每次接收完UDP数据后，重置长度。否则可能会导致下次收到数据包被截断。
            if (receivePacket != null) {
                receivePacket.setLength(BUFFER_LENGTH);
            }
            try {
                clientThread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void stopUDPSocket() {
        isThreadRunning = false;
        receivePacket = null;
        if (clientThread != null) {
            clientThread.interrupt();
        }
        if (client != null) {
            client.close();
            client = null;
        }
        if (timer != null) {
            timer.exit();
        }
    }

    /**
     * 启动心跳，timer 间隔十秒
     */
    private void startHeartbeatTimer() {
        timer = new HeartbeatTimer();
        timer.setOnScheduleListener(new HeartbeatTimer.OnScheduleListener() {
            @Override
            public void onSchedule() {
                Log.d(TAG, "timer is onSchedule...");
                long duration = System.currentTimeMillis() - lastReceiveTime;
                Log.d(TAG, "duration:" + duration);
                if (duration > TIME_OUT) {//若超过两分钟都没收到我的心跳包，则认为对方不在线。
                    Log.d(TAG, "超时，对方已经下线");
                    scanText = "离线，等待设备上线";
                    // 刷新时间，重新进入下一个心跳周期
                    lastReceiveTime = System.currentTimeMillis();
                } else if (duration > HEARTBEAT_MESSAGE_DURATION) {//若超过十秒他没收到我的心跳包，则重新发一个。
//                    String timeMillis = String.valueOf(System.currentTimeMillis());
//                    Log.e(TAG, "onSchedule: " + timeMillis );
                    String string = "HeatBeat";
                    sendMessage(string,"192.168.1.91");
                }
            }

        });
        timer.startTimer(0, 1000 * 2);
    }

    /**
     * 发送心跳包
     *
     * @param message
     */
    public void sendMessage(final String message,String ip) {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    InetAddress targetAddress = InetAddress.getByName(ip);
                    DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), targetAddress, CLIENT_PORT);

                    if(client == null){
                        stopUDPSocket();
                        startUDPSocket();
                    }
                    client.send(packet);

                    // 数据发送事件
                    Log.d(TAG, "数据发送成功:" + message);

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });
    }


}